﻿using System;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using O1.Data;
using O1.Data.Traversal;
using O1.Data.Traversal.Expressions;

namespace Tests.O1.Data.Traversal.Expressions
{
    [TestClass]
    public class PortableExpressionTests
    {
        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveDatePropertyExpressionAsExpected()
        {
            var filter = new StubUnaryExpression();
            filter.DatePropertyFilter = p => p.Key == 50 && p.Value < new DateTime(2015, 1,1);
            filter.Evaluate(new DateProperty(50, new DateTime(2014, 12, 31))).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeDatePropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.DatePropertyFilter = p => p.Key == 49 && p.Value < new DateTime(2015, 1, 1);
            filter.Evaluate(new DateProperty(50, new DateTime(2014, 12, 31))).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteDatePropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new DateProperty(50, new DateTime(2014, 12, 31))).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteDatePropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new DateProperty(50, new DateTime(2014, 12, 31))).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveDateTimePropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.DateTimePropertyFilter = p => p.Key == 50 && p.Value < new DateTimeOffset(2015, 1, 1, 0, 0, 0, TimeSpan.Zero);
            filter.Evaluate(new DateTimeProperty(50, new DateTimeOffset(2014, 1, 1, 0, 0, 0, TimeSpan.Zero))).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeDateTimePropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.DateTimePropertyFilter = p => p.Key == 49 && p.Value < new DateTimeOffset(2015, 1, 1, 0, 0, 0, TimeSpan.Zero);
            filter.Evaluate(new DateTimeProperty(50, new DateTimeOffset(2014, 12, 31, 0, 0, 0, TimeSpan.Zero))).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteDateTimePropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new DateTimeProperty(50, new DateTimeOffset(2015, 1, 1, 0, 0, 0, TimeSpan.Zero))).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteDateTimePropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new DateTimeProperty(50, new DateTimeOffset(2015, 1, 1, 0, 0, 0, TimeSpan.Zero))).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveDecimalPropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.DecimalPropertyFilter = p => p.Key == 50 && p.Value < 58m;
            filter.Evaluate(new DecimalProperty(50, 55m)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeDecimalPropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.DecimalPropertyFilter = p => p.Key == 49 && p.Value == 1040.04m;
            filter.Evaluate(new DecimalProperty(50, 1222355)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteDecimalPropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new DecimalProperty(50, 3214)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteDecimalPropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new DecimalProperty(50, 55667)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveHashPropertyExpressionAsExpected()
        {
            var value = Guid.NewGuid();
            var filter = new UnaryExpression();
            filter.HashPropertyFilter = p => p.Key == 50 && p.Value == value;
            filter.Evaluate(new HashProperty(50, value)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeHashPropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.HashPropertyFilter = p => p.Key == 49 && p.Value == Guid.NewGuid();
            filter.Evaluate(new HashProperty(50, Guid.NewGuid())).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteHashPropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new HashProperty(50, Guid.NewGuid())).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteHashPropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new HashProperty(50, Guid.NewGuid())).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveInt16PropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.Int16PropertyFilter = p => p.Key == 50 && p.Value < 58;
            filter.Evaluate(new Int16Property(50, 55)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeInt16PropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.Int16PropertyFilter = p => p.Key == 49 && p.Value == 1040;
            filter.Evaluate(new Int16Property(50, 12355)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteInt16PropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new Int16Property(50, 3214)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteInt16PropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new Int16Property(50, 5667)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveInt32PropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.Int32PropertyFilter = p => p.Key == 50 && p.Value < 58;
            filter.Evaluate(new Int32Property(50, 55)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeInt32PropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.Int32PropertyFilter = p => p.Key == 49 && p.Value == 1040;
            filter.Evaluate(new Int32Property(50, 12355)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteInt32PropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new Int32Property(50, 3214)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteInt32PropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new Int32Property(50, 5667)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositiveInt64PropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.Int64PropertyFilter = p => p.Key == 50 && p.Value < 58;
            filter.Evaluate(new Int64Property(50, 55)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeInt64PropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.Int64PropertyFilter = p => p.Key == 49 && p.Value == 1040;
            filter.Evaluate(new Int64Property(50, 12355)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteInt64PropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(new Int64Property(50, 3214)).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteInt64PropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(new Int64Property(50, 5667)).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesPositivStringPropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.StringPropertyFilter = p => p.Key == 50 && p.Value == "test1";
            filter.Evaluate(StringProperty.Create(50, "test1")).Should().Be(ObservationStates.Interested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterExecutesNegativeStringPropertyExpressionAsExpected()
        {
            var filter = new UnaryExpression();
            filter.StringPropertyFilter = p => p.Key == 49 && p.Value == "test32";
            filter.Evaluate(StringProperty.Create(44, "whatever")).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteStringPropertyFilterWhenNullAndIsUninterestedByDefault()
        {
            var filter = new UnaryExpression();
            filter.Evaluate(StringProperty.Create(50, "test")).Should().Be(ObservationStates.Uninterested);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void UnaryFilterDoesNotExecuteStringPropertyFilterWhenNullAndInterestIsSetToInterested()
        {
            var filter = new UnaryExpression();
            filter.DefaultInterest = ObservationStates.Interested;
            filter.Evaluate(StringProperty.Create(50, "test")).Should().Be(ObservationStates.Interested);
        }
    }
}
